---
title: Linux 基础：用户、用户组与权限管理
description: 深入理解 Linux 的用户、用户组、文件权限（rwx）、特殊权限（SUID/SGID/Sticky Bit）以及访问控制列表（ACL）。
---

import { Callout } from 'fumadocs-ui/components/callout';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
import { File, Folder } from 'lucide-react';

## Linux 用户与用户组基础

在 Linux 系统中，每个用户都有一个唯一的身份标识（UID），并且属于一个或多个用户组（GID）。这种设计是 Linux 多用户、多任务特性的基石，也是实现资源隔离和权限控制的核心机制。

- **用户（User）**：系统中的操作实体，可以是真人用户或系统服务。每个用户都有一个主目录、一个默认 Shell 和一个唯一的 UID。超级用户 `root`（UID 为 0）拥有系统的最高权限。
- **用户组（Group）**：用户的集合。通过将用户加入不同的组，可以方便地对一组用户进行统一的权限管理。每个用户至少属于一个主组（Primary Group），还可以属于多个附加组（Supplementary Groups）。

### 相关重要文件

- `/etc/passwd`：存储用户信息（用户名、UID、主组 GID、主目录、Shell 等），密码已加密并移至 `/etc/shadow`。
- `/etc/shadow`：存储用户加密后的密码和密码策略。
- `/etc/group`：存储用户组信息（组名、GID、组成员列表）。
- `/etc/gshadow`：存储用户组的加密信息，例如组密码。
- `/etc/sudoers`：定义了哪些用户或用户组可以使用 `sudo` 命令临时获取 `root` 权限。

---

## 用户管理命令

管理用户是系统管理员的基本职责。

### `useradd`：创建新用户

用于创建一个新用户账户。

```bash
# 创建一个名为 newuser 的用户，并创建其主目录
sudo useradd -m newuser

# 创建用户时指定主目录、Shell 和用户组
sudo useradd -d /home/custom_home -s /bin/zsh -g users -G wheel,dev newuser2
```

**常用参数**：
- `-m`：创建用户的主目录（`/home/<username>`）。
- `-d <目录>`：指定用户的主目录。
- `-s <Shell>`：指定用户的登录 Shell。
- `-g <主组>`：指定用户的主组。
- `-G <附加组>`：指定用户的附加组（多个组用逗号分隔）。
- `-u <UID>`：指定用户的 UID。

### `passwd`：设置用户密码

为用户设置或修改密码。

```bash
# 为 newuser 设置密码（需要输入两次密码）
sudo passwd newuser

# 删除用户的密码，使其无法通过密码登录
sudo passwd -d newuser
```

### `usermod`：修改用户信息

用于修改已存在用户的信息。

```bash
# 将用户 newuser 的登录 Shell 修改为 /bin/zsh
sudo usermod -s /bin/zsh newuser

# 将用户 newuser 添加到 wheel 附加组
sudo usermod -aG wheel newuser

# 锁定用户账户，使其无法登录
sudo usermod -L newuser

# 解锁用户账户
sudo usermod -U newuser
```
**`-aG`** 中的 `-a` 表示追加（append），如果只用 `-G`，会覆盖用户原有的所有附加组。

### `userdel`：删除用户

用于删除用户账户。

```bash
# 删除用户 newuser，但不删除其主目录
sudo userdel newuser

# 删除用户 newuser，并同时删除其主目录和邮件池
sudo userdel -r newuser
```

### `su`：切换用户

`su` (Switch User) 命令用于在不同用户账户之间切换。

```bash
# 切换到 root 用户（需要输入 root 密码）
su

# 切换到 root 用户，并加载 root 用户的环境变量
su -

# 切换到 newuser 用户
su newuser

# 切换到 newuser 用户，并加载其环境变量
su - newuser
```

<Callout title="su vs sudo">
- `su` 需要目标用户的密码，主要用于从普通用户切换到 `root`。
- `sudo <命令>` 使用当前用户的密码进行验证，以 `root` 权限执行单个命令，更安全、更可控，是推荐的做法。
</Callout>

---

## 用户组管理命令

### `groupadd`：创建新用户组

```bash
# 创建一个名为 developers 的用户组
sudo groupadd developers
```

### `groupmod`：修改用户组信息

```bash
# 将 developers 组的 GID 修改为 1001
sudo groupmod -g 1001 developers

# 将 developers 组重命名为 engineers
sudo groupmod -n engineers developers
```

### `groupdel`：删除用户组

```bash
# 删除 engineers 用户组
sudo groupdel engineers
```
<Callout title="注意">
如果任何用户将该组作为主组，则必须先删除该用户或更改其主组，然后才能删除该组。
</Callout>

### `gpasswd`：管理组成员

`gpasswd` 是一个管理 `/etc/group` 和 `/etc/gshadow` 的强大工具。

```bash
# 将用户 newuser 添加到 developers 组
sudo gpasswd -a newuser developers

# 将用户 newuser 从 developers 组中移除
sudo gpasswd -d newuser developers

# 设置组管理员（只有组管理员和 root 可以添加/删除成员）
sudo gpasswd -A user1,user2 developers
```

---

## 文件权限管理

Linux 文件权限是其安全模型的核心。使用 `ls -l` 可以看到权限信息。

```
-rw-r--r-- 1 user group 4096 Dec 1 10:00 file.txt
drwxr-xr-x 2 user group 4096 Dec 1 10:00 directory/
```

权限字段分为 4 部分：
1.  **文件类型**：`-`（普通文件）、`d`（目录）、`l`（符号链接）等。
2.  **所有者权限 (User)**：文件所有者拥有的权限。
3.  **所属组权限 (Group)**：文件所属组成员拥有的权限。
4.  **其他用户权限 (Others)**：其他所有用户拥有的权限。

每组权限包含三个字符：`r` (读), `w` (写), `x` (执行)。

| 权限 | 对文件的影响 | 对目录的影响 |
| :--- | :--- | :--- |
| **r (读)** | 可以读取文件内容。 | 可以列出目录中的文件和子目录列表 (`ls`)。 |
| **w (写)** | 可以修改文件内容。 | 可以在目录中创建、删除、重命名文件和子目录。 |
| **x (执行)** | 可以作为命令执行该文件。 | 可以进入该目录 (`cd`)。 |

### `chmod`：修改文件权限

`chmod` 可以使用符号模式或数字模式来修改权限。

<Tabs items={['符号模式', '数字模式']}>
  <Tab value="符号模式">
    语法直观，易于理解。
    - `u` (user), `g` (group), `o` (others), `a` (all)
    - `+` (添加权限), `-` (移除权限), `=` (设置权限)

    ```bash
    # 为所有者添加执行权限
    chmod u+x script.sh

    # 为所属组和其他用户移除写权限
    chmod go-w data.txt

    # 设置权限为：所有者读写，所属组读，其他用户无权限
    chmod u=rw,g=r,o= data.txt

    # 对目录及其下所有内容递归地添加读写权限给所属组
    chmod -R g+rw project/
    ```
  </Tab>
  <Tab value="数字模式">
    使用八进制数字表示权限，简洁高效。
    - `r` = 4
    - `w` = 2
    - `x` = 1

    将每组的权限数字相加即可：
    - `rwx` = 4 + 2 + 1 = 7
    - `rw-` = 4 + 2 + 0 = 6
    - `r-x` = 4 + 0 + 1 = 5
    - `r--` = 4 + 0 + 0 = 4

    ```bash
    # 设置权限为 -rwxr-xr-x (所有者读写执行，组读执行，其他读执行)
    chmod 755 script.sh

    # 设置权限为 -rw-rw-r-- (所有者和组读写，其他只读)
    chmod 664 config.ini

    # 递归地将目录下所有文件权限设为 644，所有目录设为 755
    find . -type f -exec chmod 644 {} \;
    find . -type d -exec chmod 755 {} \;
    ```
  </Tab>
</Tabs>

### `chown`：修改文件所有者和所属组

```bash
# 将 file.txt 的所有者修改为 newuser
sudo chown newuser file.txt

# 将 file.txt 的所有者修改为 newuser，所属组修改为 developers
sudo chown newuser:developers file.txt

# 递归地修改 project/ 目录及其下所有内容的所有者和所属组
sudo chown -R newuser:developers project/
```

### `chgrp`：修改文件所属组

```bash
# 将 file.txt 的所属组修改为 developers
sudo chgrp developers file.txt
```

---

## 特殊权限

除了基本的 `rwx` 权限，Linux 还提供了三种特殊权限。

### SUID (Set User ID)

- **数字表示**：4
- **符号表示**：`s` (在所有者执行权限位上)
- **作用**：当一个可执行文件设置了 SUID 权限后，任何用户在执行该文件时，其进程的有效用户 ID (EUID) 将暂时变为该文件的**所有者**。
- **典型应用**：`passwd` 命令。普通用户执行 `passwd` 时，需要修改 `/etc/shadow` 文件，而该文件只有 `root` 可写。`passwd` 程序的所有者是 `root` 且设置了 SUID，因此普通用户执行时能临时获得 `root` 权限来修改密码文件。

```bash
# ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 63736 Jul 27  2021 /usr/bin/passwd

# 设置 SUID
chmod u+s /path/to/executable
chmod 4755 /path/to/executable
```

### SGID (Set Group ID)

- **数字表示**：2
- **符号表示**：`s` (在所属组执行权限位上)
- **作用**：
    1.  **对可执行文件**：执行时，进程的有效组 ID (EGID) 变为文件所属组。
    2.  **对目录**：在该目录下创建的任何新文件或子目录，其所属组将自动继承该目录的所属组，而不是创建者的主组。
- **典型应用**：用于协作目录。一个项目组 `developers` 的共享目录设置 SGID 后，所有成员在该目录下创建的文件都属于 `developers` 组，方便共享和管理。

```bash
# 设置 SGID
chmod g+s /path/to/shared_directory
chmod 2775 /path/to/shared_directory
```

### Sticky Bit (粘滞位)

- **数字表示**：1
- **符号表示**：`t` (在其他用户执行权限位上)
- **作用**：主要用于目录。当一个目录设置了粘滞位后，该目录下的文件只有**文件的所有者**或 **`root`** 才能删除或重命名，即使其他用户对该目录有写权限也不行。
- **典型应用**：`/tmp` 目录。所有用户都可以在 `/tmp` 中创建文件，但为了防止用户误删他人的临时文件，`/tmp` 设置了粘滞位。

```bash
# ls -ld /tmp
drwxrwxrwt 1 root root 12288 Dec  1 12:00 /tmp

# 设置粘滞位
chmod +t /path/to/public_directory
chmod 1777 /path/to/public_directory
```

---

## 访问控制列表 (ACL)

标准 `ugo` 权限模型有时不够用。例如，你想让某个文件被 `user1` 和 `user2` 访问，但他们不属于同一个组。这时就需要 ACL。

ACL 允许你为特定的用户或用户组设置独立的权限。

### `setfacl`：设置 ACL

```bash
# 确保文件系统已启用 ACL (大多数现代发行版默认开启)
# sudo tune2fs -o acl /dev/sda1
# sudo mount -o remount,acl /

# 为用户 newuser 添加对 file.txt 的读写权限
setfacl -m u:newuser:rw- file.txt

# 为 developers 组添加对 file.txt 的读权限
setfacl -m g:developers:r-- file.txt

# 移除 newuser 的 ACL 权限
setfacl -x u:newuser file.txt

# 移除所有 ACL 权限
setfacl -b file.txt

# 递归地为目录设置默认 ACL，使新创建的文件继承这些 ACL
setfacl -R -m d:u:newuser:rwx,d:g:developers:rwx /path/to/project
```

### `getfacl`：查看 ACL

当一个文件设置了 ACL 后，`ls -l` 的权限位末尾会有一个 `+` 号。

```bash
$ ls -l file.txt
-rw-rw-r--+ 1 user group 0 Dec  1 12:30 file.txt

$ getfacl file.txt
# file: file.txt
# owner: user
# group: group
user::rw-
user:newuser:rw-    # ACL 条目
group::r--
group:developers:r-- # ACL 条目
mask::rw-
other::r--
```